<template>
  <!-- 视频会议 -->
  <div class="video_meeting">
    <div class="meeting_box">
      <div :class="{'meeting_fl_box':true, fl_slot: rightStatus, fl_flex: remoteStatus}">
        <img
          src="../../assets/img/fz_camera.png"
          alt=""
          class="fz_icon"
          @click.stop="changeCamera"
          v-if="isPhone"
        >
        <div class="between_video_box" id="betweenVideoBox" v-show="speechViewStatus">
          <video ref="betweenVideo" id="betweenVideo" autoplay playsinline @click="handleClickAsideBtn" :class="{'between_video':true, overturn: overturnStatus}"></video>
        </div>
        <div id="remoteMediasVideo" ref="remoteMediasVideo" :class="{'speech_remote':speechViewStatus, 'aside_show':asideBtnStatus, 'aside_hide':!asideBtnStatus}" @click="handleClickRemote($event)">
          <div class="userCard" id="localMedia" ref="localMedia"></div>
        </div>
        <img v-show="!asideBtnStatus" class="aside_img" src="../../assets/img/btnhide.png" alt="" @click="handleClickAsideBtn">
      </div>
      <div class="nine_pal_video_box" v-show="clickNinePalaceVideoStatus">
        <video ref="ninePalaceVideo" :class="{'nine_palace_video':clickScreenVidStatus}" id="ninePalaceVideo" @click="handleClickNidePalaceVideo" autoplay playsinline ></video>
      </div>
      <div :class="{'meeting_fr_box':true, fr_slot: rightStatus}">
        <div class="fr_header">
          <div class="fr_header_fl">{{rHeaderTitle}}</div>
          <img src="../../assets/img/close.png" alt="" @click="closeRightFunc">
        </div>
        <member-list
          v-show="rightType=='member'"
          :memberArr='memberArr'
        ></member-list>
        <message-list
          :msg='msg'
          :selfName='selfName'
          v-show="rightType=='message'"
        ></message-list>
      </div>
    </div>
    <control-btn
      ref="controlBtn"
      @showFr="showFr"
      @changeRangeView="changeRangeView"
      @exitMeeting='exitMeeting'
      @chooseVideo='getVideoInfo'
      :msg='msg'
      v-if="!reloadStatus"
    ></control-btn>
    <div class="refresh_box">
      <button @click="refresh" :disabled="refreshBtnStatus">刷新</button>
    </div>
  </div>
</template>

<script>
import controlBtn from '@/components/meetingControl/index'
import memberList from '@/components/memberList/index'
import messageList from '@/components/messageList/index'

export default {
  name: "videomeeting",
  data() {
    return {
      h: this.$route.query.h,
      remoteStatus: false,
      noPeers: true,
      minimizeUrl: require('../../assets/img/minimize.png'),
      isPhone: navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i),
      promptClass: 'pc_prompt',
      rightStatus: false,
      rightType: '',
      rHeaderTitle: '',
      msg: {},
      selfName: '',
      memberArr: [],
      exchangeLocalPeerId: '',
      speechViewStatus: false,
      overturnStatus: false,
      asideBtnStatus: true,
      interval: null,
      clickNinePalaceVideoStatus: false,
      clickScreenVidStatus: false,
      reloadStatus: false, // 是否重新加载底部会议控制按钮
      refreshBtnStatus: false,
      n: this.$route.query.n || null, // 链接上的名字
      roomInfo: {},
      selfInfo: {}
    };
  },

  watch: {
    memberArr: {
      handler (val) {
        if (val.length > 0) {
          if (document.querySelectorAll('.userCard').length == 1) {
            document.querySelector('.userCard').classList.add('onlyone')
            return
          }
          var class_name
          [2, 3, 4].indexOf(document.querySelectorAll('.userCard').length) != -1
            ? class_name = 'remote_media'
            : class_name = 'remote_media_s'
          document.querySelectorAll('.userCard').forEach(item => {
            if (item.className.includes('onlyone')) item.classList.remove('onlyone')
            if (document.querySelectorAll('.userCard').length == 4) item.classList.remove('remote_media_s')
            item.classList.add(class_name)
          })
        }
      },
      immediate: true
    }
  },

  components: {
    controlBtn,
    memberList,
    messageList
  },

  created() {
    window.addEventListener('beforeunload', e => this.refreshPage(e))
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('beforeunload', e => this.refreshPage(e))
    })
    if (this.isPhone) this.promptClass = 'phone_prompt'
  },

  mounted() {
    this.joinRoom()
  },

  methods: {
    changeCamera () {
      this.$refs.controlBtn.switchDevice()
    },
    /** 拿到摄像头信息 */
    async getVideoInfo (device) {
      if (device) {
        let { deviceId } = device
        this.umvideo.setMediaEnable(this.umvideo.mediaType.video, false)
        this.umvideo.setMediaEnable(this.umvideo.mediaType.video, true, deviceId)
      }
    },
    /** 关闭右侧弹出框 */
    closeRightFunc () {
      this.rightStatus = false
      this.$refs.controlBtn.handleParentResetStatus()
    },
    /** 重新连接 */
    refresh () {
      this.refreshBtnStatus = true
      this.reloadStatus = true
      this.$nextTick(() => {
        this.reloadStatus = false
        this.$nextTick(async () => {
          if (!await this.$refs.controlBtn.handleSupportStatus()) return
        })
      })
      this.memberArr = []
      this.umvideo.exitRoom()
      this.handleJoinRoom(this.selfName)
    },
    /** 点击右侧收回展开图标 */
    handleClickAsideBtn () {
      this.asideBtnStatus = !this.asideBtnStatus
      let domIDArr = []
      this.$refs.remoteMediasVideo.childNodes.forEach(item => {
        item.childNodes && item.childNodes.forEach(v => v.nodeName == 'VIDEO' && domIDArr.push(v.id))
      })
      domIDArr.forEach(item => this.umvideo.setBandwidth(!this.asideBtnStatus ? 'low' : 'high', item, 'consumer'))

      if (this.isPhone) {
        if (this.asideBtnStatus) {
          document.querySelector('#remoteMediasVideo').setAttribute('style', 'width:25%!important')
          document.querySelector('#betweenVideoBox').setAttribute('style', 'width:calc(75% - 20px);height:auto;')
        } else {
          document.querySelector('#remoteMediasVideo').setAttribute('style', 'width:0%!important')
          document.querySelector('#betweenVideoBox').setAttribute('style', 'width:calc(100% - 20px);height:auto;')
        }
      }
    },
    /** 切换视图排列 */
    changeRangeView () {
      this.speechViewStatus = !this.speechViewStatus
      this.clickNinePalaceVideoStatus = false
      if (!this.asideBtnStatus) this.asideBtnStatus = true
      if (this.isPhone) {
        if (this.speechViewStatus) {
          this.$nextTick(() => {
            ;[{
              q_name: '.speech_remote',
              q_style: 'width:25%!important;'
            }, {
              q_name: '.meeting_fl_box',
              q_style: 'justify-content: space-between;'
            }, {
              q_name: '.between_video_box',
              q_style: 'width:calc(75% - 20px);height:auto;'
            }].forEach(item => document.querySelector(item['q_name']).setAttribute('style', item['q_style']))
          })
        } else {
          ['.speech_remote', '.meeting_fl_box', '.between_video', '.between_video_box'].forEach(item => document.querySelector(item).removeAttribute('style'))
        }
      }
      if (this.speechViewStatus) {
        let localMediaChild = this.$refs.localMedia.children
        this.overturnStatus = localMediaChild.length === 1 && localMediaChild[0].className === 'screenVid' // 仅分享屏幕后切换视图
        if (localMediaChild[0]) this.$refs.betweenVideo.srcObject = localMediaChild[0].srcObject
      }
      if (!this.speechViewStatus) {
        this.$refs.betweenVideo.pause()
        this.$refs.betweenVideo.srcObject = null
      }
    },
    /** 点击remote */
    handleClickRemote (e) {
      if (e.target.nodeName == 'VIDEO') {
        if (this.speechViewStatus) {
          this.handleClickSpeechViewVideo(e)
        }

        let clickedClassName = e.target.className
        if (this.speechViewStatus) {
          this.$refs.betweenVideo.srcObject = e.target.srcObject
          this.$refs.betweenVideo.play()
          this.overturnStatus = clickedClassName == 'screenVid' || clickedClassName == 'scr'
        } else {
          let localMediaChild = this.$refs.localMedia.children
          if (['screenVid', 'screenVid s_vid'].includes(clickedClassName) && localMediaChild.length > 1) {
            [localMediaChild[0].srcObject, e.target.srcObject] = [e.target.srcObject, localMediaChild[0].srcObject]
            let func = clickedClassName.indexOf('s_vid') != -1 ? func = 'remove' : func = 'add'
            localMediaChild[0].classList[func]('c_vid')
            e.target.classList[func]('s_vid')
            return
          }
          this.clickNinePalaceVideoStatus = true
          this.$refs.ninePalaceVideo.srcObject = e.target.srcObject
          this.$refs.ninePalaceVideo.play()
          this.clickScreenVidStatus = ['vid c_vid', 'screenVid', 'scr'].includes(e.target.className)
        }
      }
    },
    /** 演讲者模式下，点击视频 */
    handleClickSpeechViewVideo (e) {
      let domIDArr = [], clickedVideoId = ''
      clickedVideoId = e.target.id

      this.$refs.remoteMediasVideo.childNodes.forEach(item => {
        item.childNodes.forEach(v => v.nodeName == 'VIDEO' && domIDArr.push(v.id))
      })
      domIDArr.forEach(item => {
        clickedVideoId == item
          ? this.umvideo.setBandwidth('high', clickedVideoId, 'consumer')
          : this.umvideo.setBandwidth('low', item, 'consumer')
      })
    },
    /** 点击放大后的视频 */
    handleClickNidePalaceVideo () {
      this.clickNinePalaceVideoStatus = false
      this.$refs.ninePalaceVideo.srcObject = null
      this.$refs.ninePalaceVideo.pause()
    },
    /** 处理微信分享 */
    handleWXShare () {
      if (this.$store.state.functionMap.isWx) {
        this.$WXShare({
          title: '联信UMRTC会议系统',
          desc: `${this.selfName}发起的视频会议`,
          link: location.href,
          imgUrl: location.origin + '/static/img/um.png'
        })
      }
    },
    /** 初始化 */
    initUmVideo () {
      this.umvideo.setup({
        listenPort: this.$store.state.functionMap.listenPort,
        signalServer: this.$store.state.functionMap.signalServer,
        localMedia,
        remoteMedias: this.$refs.remoteMediasVideo,
        audio: {
          echoCancellation: true // 回声消除
        }
      })
    },
    /** 加入房间 */
    async joinRoom () {
      if (!await this.$refs.controlBtn.handleSupportStatus()) return

      this.initUmVideo()
      if (this.n) {
        this.handleName(this.n)
      } else {
        this.promptName()
          .then(name => this.handleName(name))
      }
    },
    handleName (name) {
      this.selfName = name
      this.setGlobalSetting('myname', name)
      this.handleWXShare()
      this.handleJoinRoom(name)
    },
    /** 处理加入房间的逻辑 */
    handleJoinRoom (name) {
      this.umvideo.joinRoom(this.h, name, this.$route.query.m, async (res) => {
        this.roomInfo = res.roomInfo
        this.selfInfo = res.myInfo
        res.roomInfo.peers.forEach(item => {
          this.memberArr.push({ id: item.id, name: item.name })
          this.$nextTick(() => {
            if (item.name != this.selfName && document.querySelector(`#um_${item.id} .userInfo`)) {
              document.querySelector(`#um_${item.id} .userInfo`).innerHTML = item.name
            }
          })
        })
        this.$store.commit('setSelfID', res.myInfo.id)
        this.noPeers = res.roomInfo.peers.length <= 1
        try {
          await this.umvideo.setMediaEnable(this.umvideo.mediaType.audio, true)
          await this.umvideo.setMediaEnable(this.umvideo.mediaType.video, true)
          this.refreshBtnStatus = false
          this.$refs.controlBtn.getDeviceIDList()
        } catch (error) {
          this.$notify.error({
            title: '提示',
            message: `无法打开本地视频或音频设备${error}`
          })
        }
        [
          'watchRemoteAdd',
          'watchRemoteExit',
          'watchGetMsg',
          'watchLocalMediaAdd',
          'watchRemoteMediaAdd'
        ].forEach(v => this[v]())

        this.$refs.controlBtn.handleParentDoFunc()
      })
    },
    /** 弹出来输入名字 */
    promptName () {
      return new Promise(resolve => {
        this.$prompt('请输入姓名', '提示', {
          confirmButtonText: '确定',
          showClose: false,
          closeOnPressEscape: false,
          closeOnClickModal: false,
          customClass: this.promptClass,
          inputValue: this.getGlobalSetting('myname') || '',
          beforeClose: (action, instance, done) => {
            if (action === 'confirm' && !instance.inputValue) {
              this.$notify.error({
                title: '提示',
                message: '请输入名字！'
              })
              return false
            }
            done()
          }
        }).then(({ value }) => {
          resolve(value)
        }).catch(() => {
          this.umvideo.exitRoom()
          this.$router.push({name: 'roomindex'})
        });
      })
    },
    /** 监听有人加入 */
    watchRemoteAdd () {
      this.umvideo.on(this.umvideo.EVENTS.addPeer, e => {
        if (e) {
          this.noPeers = false
          this.memberArr = [...this.memberArr, { id: e.id, name: e.name }]
          this.$nextTick(() => {
            document.getElementById('memberUl').scrollTop = document.getElementById('memberUl').scrollHeight
            document.querySelector(`#um_${e.id} .userInfo`).innerHTML = e.name
          })
        }
      })
    },
    /** 监听localMediaAdd */
    watchLocalMediaAdd () {
      this.umvideo.on(this.umvideo.EVENTS.localMediaAdd, e => {
        if (e) {
          setTimeout(() => {
            e.play()
          }, 200);
        }
      })
    },
    /** 监听mediaAdd */
    watchRemoteMediaAdd () {
      clearInterval(this.interval)
      this.interval = setInterval(() => {
        document.querySelectorAll('video').forEach(item => item.play())
      }, 1000);
      this.umvideo.on(this.umvideo.EVENTS.remoteMediaAdd, e => {
        if (e && e.nodeName == 'VIDEO') {
          e.setAttribute('preload', 'auto')
          e.setAttribute('webkit-playsinline', 'true')
          e.setAttribute('x5-video-player-type', 'h5')
          e.setAttribute('x-webkit-airplay', 'allow')
        }
      })
    },
    /** 监听有人退出 */
    watchRemoteExit () {
      this.umvideo.on(this.umvideo.EVENTS.removePeer, e => {
        if (e) {
          /** 如果切换到中间大屏的人退出了，中间大屏将显示本人视频 */
          if (this.exchangeLocalPeerId && e.id == this.exchangeLocalPeerId) {
            this.$refs.middleVideo.click()
          }
          this.noPeers = this.$refs.remoteMediasVideo.innerHTML.length <= 0
          this.memberArr = this.memberArr.filter(item => item.id !== e.id)
        }
      })
    },
    /** 监听收到消息 */
    watchGetMsg () {
      this.umvideo.on(this.umvideo.EVENTS.userMsg, e => this.msg = e)
    },
    /** 显示成员列表或者消息 */
    showFr (val) {
      this.rightStatus = this.rightType == val ? !this.rightStatus : true
      this.rightType = val
      this.rHeaderTitle = val === 'message' ? '消息' : '成员'
    },
    /** 退出房间 */
    exitMeeting () {
      this.refreshPage()
      this.$router.replace({name: 'roomindex'})
    },
    /** 页面刷新 */
    refreshPage () {
      this.umvideo.exitRoom()
      this.interval && clearInterval(this.interval)
    }
  }
};
</script>

<style lang="scss" scoped>
.video_meeting {
  height: 100%;
  .meeting_box {
    height: calc(100% - 60px);
    background-color: #323232;
    display: flex;
    .minimize {
      width: 30px;
      position: absolute;
      top: 5px;
      right: 310px;
      z-index: 1;
      cursor: pointer;
    }
    .phone_m {
      right: 36.5%;
    }
    .open_minimize {
      right: 5px;
    }
    .meeting_fl_box {
      height: 100%;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      overflow-y: auto;
      > div {
        width: 100%;
      }
      .fz_icon {
        position: absolute;
        left: 15px;
        top: 15px;
        z-index: 10;
        width: 25px;
        height: 25px;
      }
      .fl_flex {
        flex: 1;
      }
      #remoteMediasVideo {
        width: 90%;
        height: 90%;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        justify-content: center;
        z-index: 0;
        overflow-x: hidden;
        position: relative;
      }
      .overturn {
        transform: none;
      }
      .aside_img {
        position: absolute;
        right: 0;
        top: 50%;
        bottom: 50%;
        cursor: pointer;
      }
      .between_video_box {
        width: calc(100% - 320px);
        height: 100%;
        margin: 0 10px;
        box-shadow: 0 0 5px #000;
        background: url('../../assets/img/user.svg') no-repeat bottom;
        background-size: auto 85%;
        display: flex;
        justify-content: center;
        align-items: center;
        .between_video {
          width: 100%;
        }
      }
      .speech_remote {
        width: 300px!important;
        height: 100%!important;
        display: block !important;
        overflow-y: auto;
        z-index: 0;
        transition: all .8s;
        .aside_btn {
          position: absolute;
          right: 288px;
          z-index: 1;
          cursor: pointer;
          top: 50%;
          bottom: 50%;
        }
        .remote_media {
          width: 100%!important;
          height: auto!important;
        }
      }
      .aside_hide {
        width: 0!important;
      }
    }
    .meeting_fr_box {
      height: 100%;
      width: 300px;
      display: none;
      background-color: #fff;
      .fr_header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 15px 20px;
        border-bottom: 1px solid #F0F0F0;
        img {
          cursor: pointer;
        }
      }
    }
    .fl_slot {
      width: calc(100% - 300px);
    }
    .fr_slot {
      display: block;
    }
    @keyframes opa {
      from {opacity: 0;}
      to {opacity: 1;}
    }
    .nine_pal_video_box {
      position: absolute;
      z-index: 1;
      left: 0;
      right: 0;
      top: 0;
      bottom: 60px;
      animation: opa 500ms;
      background-color: #323232;
      video {
        object-fit: contain;
      }
      .nine_palace_video {
        transform: none;
      }
    }
  }
  .remote_box {
    width: 300px;
    height: 100%;
    position: absolute;
    right: 2px;
    top: 0;
    bottom: 54px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 0;
  }
  .phone_remote {
    width: 35%!important;
    height: calc(100% - 50px);
    .userCard {
      width: 100%;
    }
  }
  .myself {
    position: relative;
    .middle_video {
      width: 0;
    }
    video {
      width: 100%;
      height: 100%;
    }
    .userInfo {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      opacity: .7;
      background-color: #000;
      text-align: center;
      color: #fff;
      padding: 3px 0;
      z-index: 1;
    }
  }
  .refresh_box {
    position: absolute;
    z-index: 1000;
    left: 10px;
    bottom: 70px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    color: #fff;
    cursor: pointer;
    button {
      background: #fff;
    }
  }
}
</style>
<style lang="scss">
video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
#remoteMediasVideo {
  > video {
    box-shadow: 0 0 5px #000;
    margin: 0 5px;
    display: block;
  }
}
#remoteMediasVideo .userCard {
  background-color: #323232;
  position: relative;
  box-shadow: 0 0 5px #000;
  margin: 0 5px;
  overflow-y: hidden;
  .userInfo {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    opacity: .7;
    background-color: #000;
    text-align: center;
    color: #fff;
    padding: 3px 0;
    z-index: 1;
  }
}
.userCard {
  background: url('../../assets/img/user.svg') no-repeat bottom;
  background-size: auto 85%;
}
.remote_media {
  width: calc(50% - 10px)!important;
  height: calc(50% - 10px)!important;
}
.remote_media_s {
  width: calc(33% - 10px)!important;
  height: calc(33% - 10px)!important;
}
.speech_remote .remote_media,
.speech_remote .remote_media_s {
  width: 100%!important;
  height: 33%!important;
  margin: 0!important;
}
.onlyone {
  width: 100%!important;
  height: 100%!important;
  background: none;
}
.screenVid, .scr {
  transform: none;
  position: absolute;
  right: 0;
  top: 0;
  width: 25%;
  height: 25%;
  z-index: 1;
}
.c_vid {
  transform: none;
}
.s_vid {
  transform: scaleX(-1);
}
.phone_prompt {
  width: 70%;
}
</style>
